import os
import zipfile
import tarfile
import argparse

gcc_optimization_result = []

# module: [[keywords], [report_info]]
gcc_optimization_info = {
    "gcc-opt": [
        [["-finline-force="], ["LTO-binary-inline", "inline-force"]],
        [["-fcfgo-profile-use="], ["CFGO", "CFGO-PGO"]],
        [["-fcfgo-csprofile-use="], ["CFGO", "CFGO-CSPGO"]],
        [[".rto"], ["D-FOT", "dfot_tuner_sysboost"]],
    ],
    "ai4c": [
        [["Best Config", "Best Result"], ["AI4C", "应用级选项调优"]],
        [["Optimal json configuration for opentuner has been saved to loop.json"], ["AI4C", "细粒度调优"]],
        [["Error"], ["AI4C", "AI辅助编译优化-循环展开和内联调优"]],
        [["total modified CFG BB count number"], ["AI4C", "AI辅助编译优化-BOLT采样基本块修正调优"]],
        [["Optimal json configuration for opentuner has been saved to function.json"], ["AI4C", "函数级的粗粒度调优"]]
    ]
}

ai4c_log_name = [
    "compiler_option_tune.ai4c.log",
    "pass_option_tune.ai4c.log",
    "inline_unroll.ai4c.log",
    "bolt_bb.ai4c.log",
    "function_option_tune.ai4c.log"
]

gcc_template = """
                <html>
                <head>
                <meta charset="utf-8"/>
                <meta content="IE=edge" http-equiv="X-UA-Compatible"/>
                <meta content="width=device-width, initial-scale=1.0" name="viewport"/>
                <title>Document</title>
                </head>
                <body>
                <div class="header">
                      gcc编译器验收报告
                    </div>
                <div class="content">
                <div class="title">
                        配置信息
                      </div>
                <div class="info">
                <div class="left">
                <div class="left-content">
                </div>
                </div>
                <div class="right">
                <div class="text"></div>
                <div class="num"></div>
                </div>
                </div>
                <div class="table">
                <div class="title">验收详细结果</div>
                <table>
                <tr>
                <th>序号</th>
                <th>优化项</th>
                <th>优化子项</th>
                <th>使用状态</th>
                </tr>
                </table>
                </div>
                </div>
                </body>
                <script>    
                            var infoList = {};

                            // 已使能特性
                            var num = "";

                            // 验收详细结果
                            var tableList = {};




                    // 配置信息
                    var leftContentEle = document.getElementsByClassName('left-content')[0];
                     infoList.forEach(item => {{
                       let singleEle = document.createElement('div');
                       singleEle.setAttribute('class', 'single');
                       let labelEle = document.createElement('div');
                       labelEle.setAttribute('class', 'label');
                       labelEle.innerText = item.label;
                       let valueEle = document.createElement('div');
                       valueEle.setAttribute('class', 'value');
                       valueEle.innerText = item.value;
                     
                       singleEle.appendChild(labelEle);
                       singleEle.appendChild(valueEle);
                       leftContentEle.appendChild(singleEle);
                     }})


                    // 已使能特性
                    var numEle = document.getElementsByClassName('num')[0];
                    numEle.innerText = num;


                    // 验收详细结果
                    var tableEle = document.getElementsByTagName('table')[0];
                    tableList.forEach(list => {{
                      let trEle = document.createElement('tr');
                      list.forEach(item => {{
                        let tdEle = document.createElement('td');
                        tdEle.innerText = item;
                        trEle.appendChild(tdEle);
                      }})
                      tableEle.appendChild(trEle);
                    }})


                  </script>
                <style>
                    body {{
                      background-color: #222020;
                      color: #fff;
                      padding: 8px 16px;
                      margin: 0;
                      font-size: 14px;
                    }}
                    .header {{
                      font-size: 18px;
                      width: 100%;
                      line-height: 50px;
                      border-bottom: 1px solid rgb(110, 110, 110);
                    }}
                    .info {{
                      display: flex;
                      justify-content: flex-start;
                      align-items: flex-start;
                    }}
                    .left {{
                      width: 60%;
                    }}
                    .title {{
                      font-size: 16px;
                      margin: 20px 0 10px 0;
                    }}
                    .single {{
                      display: flex;
                      justify-content: flex-start;
                      align-items: center;
                      margin: 8px 0;
                    }}
                    .label {{
                      color: rgb(195, 206, 216);
                      width: 30%;
                    }}
                    .right {{
                      width: 40%;
                      text-align: center;
                    }}
                    .text {{
                      font-size: 20px;
                      color: rgb(195, 206, 216);
                    }}
                    .num {{
                      font-size: 50px;
                    }}
                    table {{
                      border: 1px solid rgb(110, 110, 110);
                      width: 100%
                    }}
                    th{{
                      font-size: 14px; 
                      padding: 5px 15px;
                      color: rgb(222, 227, 231);
                      background-color: #555353;
                    }}
                    td {{
                      padding: 2px 5px;
                      border-top: 1px solid rgb(110, 110, 110);
                      border-right: 1px solid rgb(110, 110, 110);
                    }}
                    td:last-child {{
                      border-right: none
                    }}
                  </style>
                </html>"""

tuner_report_info = [{'label': '门禁工具', 'value': 'gcc编译器验收工具'},
                     {'label': '评估结果', 'value': '未通过'}]


class AcceptanceTool(object):
    def check_keywords_in_lines(self, content, keywords):
        lines = content.splitlines()
        for line in lines:
            if all(keyword in line for keyword in keywords):
                return True
        return False

    def devkit_acceptance_report(self, compressed_report_package, module):
        start_index = len(gcc_optimization_result)
        for i in range(len(gcc_optimization_info[module])):
            keywords = gcc_optimization_info[module][i][0]
            test_result = [len(gcc_optimization_result) + 1] + gcc_optimization_info[module][i][1] + ["未使用"]
            gcc_optimization_result.append(test_result)

        if not os.path.exists(compressed_report_package):
            print("Enter a correct report package.")
            return

        file_ext = os.path.splitext(compressed_report_package)[1].lower()
        if file_ext not in (".zip", ".gz", ".bz2"):
            print("Please use the compressed package in the following format:.zip、.gz、.bz2")
            return
        decompress = {".zip": decompress_zip, ".gz": decompress_gz_bz, ".bz2": decompress_gz_bz}
        current_path = os.getcwd()
        print("Starting decompression...")
        file_names = decompress.get(file_ext)(compressed_report_package)
        
        for file in file_names:
            try:
                if not os.path.isfile(os.path.join(current_path, file)):
                    continue
                with open(os.path.join(current_path, file), 'r', encoding='utf-8') as f:
                    content = f.read()
                    for i in range(len(gcc_optimization_info[module])):
                        keywords = gcc_optimization_info[module][i][0]
                        if self.check_keywords_in_lines(content, keywords):
                            gcc_optimization_result[start_index + i][-1] = "已使用"
            except (UnicodeDecodeError, PermissionError):
                continue


    def check_keywords_in_content(self, content, keywords):
        lines = content.splitlines()
        num = len(keywords)
        cur = 0
        for keyword in keywords:
            for line in lines:
                if keyword in line:
                    cur += 1
                    break
        if cur == num:
                return True
        else:
            return False

    def devkit_acceptance_report_ai4c(self, compressed_report_package, module):
        if not os.path.exists(compressed_report_package):
            print("Enter a correct report package.")
            return
        file_ext = os.path.splitext(compressed_report_package)[1].lower()
        if file_ext not in (".zip", ".gz", ".bz2"):
            print("Please use the compressed package in the following format:.zip、.gz、.bz2")
            return

        decompress = {".zip": decompress_zip, ".gz": decompress_gz_bz, ".bz2": decompress_gz_bz}
        current_path = os.getcwd()
        print("Starting decompression...")
        file_names = decompress.get(file_ext)(compressed_report_package)

        for i in range(len(gcc_optimization_info[module])):
            for file in file_names:
                try:
                    file_path = os.path.join(current_path, file)
                    if not os.path.isfile(file_path):
                        continue
                    filename = os.path.basename(file_path)
                    if filename == ai4c_log_name[i]:
                        with open(file_path, 'r', encoding='utf-8') as f:
                            content = f.read()
                            keywords = gcc_optimization_info[module][i][0]
                            test_result = [len(gcc_optimization_result) + 1] + gcc_optimization_info[module][i][1] \
                                          + ["未使用"]
                            if filename == "inline_unroll.ai4c.log":
                                if not self.check_keywords_in_content(content, keywords):
                                    test_result[-1] = "已使用"
                            else:
                                if self.check_keywords_in_content(content, keywords):
                                    test_result[-1] = "已使用"
                            gcc_optimization_result.append(test_result)
                        break
                except (UnicodeDecodeError, PermissionError):
                    continue


def decompress_zip(compressed_report_package, file_list=[]):
    with zipfile.ZipFile(compressed_report_package, 'r') as zip:
        zip.extractall("./")
        for file in zip.namelist():
            if file.endswith('.zip'):
                decompress_zip(file)
    file_names = zip.namelist()
    file_list.extend(file_names)
    return file_list


def decompress_gz_bz(compressed_report_package):
    file_list = []
    with tarfile.open(compressed_report_package, "r") as tar:
        tar.extractall(path="./")
        file_names = tar.getnames()
        for file in file_names:
            if file.endswith('.zip'):
                decompress_zip(file, file_list=file_list)
        file_list.extend(file_names)
        return file_list


if __name__ == "__main__":
    try:
        parser = argparse.ArgumentParser(description="GCC for openEuler编译器验收工具")
        parser.add_argument('-tool', help='gcc')
        parser.add_argument('-package', help='Compressed package')
        args = parser.parse_args()
        acceptance_tool = AcceptanceTool()
        if args.tool == "gcc":
            acceptance_tool.devkit_acceptance_report(args.package, "gcc-opt")
            acceptance_tool.devkit_acceptance_report_ai4c(args.package, "ai4c")
        
            if any(result[-1] == "已使用" for result in gcc_optimization_result):
                tuner_report_info[1]["value"] = "通过"
                print("test result is successful")
            tuner_report_html = gcc_template.format(tuner_report_info, gcc_optimization_result)
            with open(os.path.join(os.getcwd(), "gcc_test_result.html"), "w", encoding="utf-8") as f:
                f.write(tuner_report_html)
            print("Decompression completed.")
            print("View the report in {}.".format(os.path.join(os.getcwd(), "gcc_test_result.html")))
        else:
            print("Enter a correct parameter, for example, -tool gcc.")

    except Exception as err:
        print(err)
        print("Enter a correct parameter.")